﻿using System;
using System.Globalization;
using System.Web.Mvc;
using System.Web.Routing;
using ManagedUIFlow.Infrastructure.Commands.FlowActionHelpers;
using ManagedUIFlow.Model;
using ManagedUIFlow.Properties;

namespace ManagedUIFlow.Infrastructure.Commands
{
    public class FlowAction : ICommand
    {
        private readonly RequestContext _requestContext;
        private ControllerBuilder _controllerBuilder;

        public FlowAction(RequestContext requestContext)
        {
            _requestContext = requestContext;
        }

        public ControllerBuilder ControllerBuilder
        {
            get
            {
                if (_controllerBuilder == null)
                {
                    _controllerBuilder = ControllerBuilder.Current;
                }
                return _controllerBuilder;
            }
            set
            {
                _controllerBuilder = value;
            }
        }

        public void Execute(ManagedFlow flow)
        {            
            if(flow == null)
                throw new ArgumentNullException("flow");

            if(string.IsNullOrEmpty(flow.Name))
                throw new InvalidOperationException();

            // Instantiate the controller and call Execute
            var factory = ControllerBuilder.GetControllerFactory();
            var controller = factory.CreateController(_requestContext, flow.Name);
            if (controller == null)
            {
                throw new InvalidOperationException(
                    String.Format(
                        CultureInfo.CurrentUICulture,
                        Resources.ControllerBuilder_FactoryReturnedNull,
                        factory.GetType(),
                        flow.Name));
            }

            var flowController = controller as FlowController;
            if (flowController != null)
                flowController.ManagedFlow = flow;

            _requestContext.RouteData.Values["action"] = flow.CurrentNavigation;

            try
            {
                controller.Execute(_requestContext);
            }
            finally
            {               
                factory.ReleaseController(controller);
            }
        }
    }
}